package service.ucenter.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.gson.Gson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import service.edu.exception.CustomException;
import service.edu.utils.HttpClientUtils;
import service.edu.utils.JwtUtil;
import service.ucenter.entity.Member;
import service.ucenter.service.MemberService;
import service.ucenter.utils.WxConstantPropertiesUtil;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.UUID;

@Controller//因为需要使用重定向所以不能用@RestController
@CrossOrigin
@RequestMapping("/api/ucenter/wx")
public class WxApiController {
    @Autowired
    private MemberService memberService;

    /**
     * 1.生成微信扫描二维码
     * 通过微信二维码登录,不需要返回数据,所以返回值不是R
     * 将通过重定向来跳转对应地址实现功能,故返回值为String
     */
    @GetMapping("login")
    public String getWxCode() {
        /**微信开放平台授权baseUrl
         * %s相当于?代表占位符
         * 注意redirect_uri需要编码处理才能作为参数
         */
        String baseUrl = "http://open.weixin.qq.com/connect/qrconnect" +
                "?appid=%s" +
                "&redirect_uri=%s" +
                "&response_type=code" +
                "&scope=snsapi_login" +
                "&state=%s" +
                "#wechat_redirect";

        /**为redirect_uri进行编码处理
         * 回调地址
         */
        String redirectUrl = WxConstantPropertiesUtil.WX_OPEN_REDIRECT_URL;
        try {
            redirectUrl = URLEncoder.encode(redirectUrl, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        /**防止csrf攻击（跨站请求伪造攻击）,一般情况下会使用一个随机数
         * 对state使用UUID.randomUUID().toString().replaceAll("-", "");
         */
        String state = UUID.randomUUID().toString().replaceAll("-", "");

        //为baseUrl填充%s内容,生成新的url
        String url = String.format(
                baseUrl,
                WxConstantPropertiesUtil.WX_OPEN_APP_ID,
                redirectUrl,
                state);

        //返回重定向地址
        return "redirect:" + url;
    }


    /**
     * 2.获取扫描人信息,添加数据
     */
    @GetMapping("/callback")
    public String callback(String code) {
        try {
            //1.根据参数获取code值,其就是临时票据,类似于验证码
            //2.微信固定地址,注意是https而不是http
            String baseAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token" +
                    "?appid=%s" +
                    "&secret=%s" +
                    "&code=%s" +
                    "&grant_type=authorization_code";

            //3.使用format拼接参数,生成accessTokenUrl
            String accessTokenUrl = String.format(baseAccessTokenUrl,
                    WxConstantPropertiesUtil.WX_OPEN_APP_ID,
                    WxConstantPropertiesUtil.WX_OPEN_APP_SECRET,
                    code);

            //4.请求accessTokenUrl该地址,以得到access_token与openid,通过httpclient发送请求
            String accessTokenInfo = HttpClientUtils.get(accessTokenUrl);

            //5.使用json转换工具gson,把accessTokenInfo这个json字符串转为map集合,然后从map根据key-value取出想要的值
            Gson gson = new Gson();
            HashMap accessTokenMap = gson.fromJson(accessTokenInfo, HashMap.class);
            String access_token = (String) accessTokenMap.get("access_token");
            String openid = (String) accessTokenMap.get("openid");

            //6.根据获得的access_token和openid再去请求微信提供的固定地址来获取到扫描账号的信息
            String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
                    "?access_token=%s" +
                    "&openid=%s";

            //7.使用format拼接参数,生成userInfoUrl
            String userInfoUrl = String.format(baseUserInfoUrl, access_token, openid);

            //8.依旧根据httpclient发送请求
            String userInfo = HttpClientUtils.get(userInfoUrl);

            //9.依旧使用json转换工具gson
            HashMap userInfoMap = gson.fromJson(userInfo, HashMap.class);
            String wxId = (String) userInfoMap.get("openid");
            String nickname = (String) userInfoMap.get("nickname");
            String headimgurl = (String) userInfoMap.get("headimgurl");
            Integer sex = (Integer) userInfoMap.get("sex");

            //10.将获得的微信账户相关信息添加到数据库中,但需要先查下数据库是否有相同账号
            QueryWrapper<Member> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("openid", wxId);
            Member user = memberService.getOne(queryWrapper);
            //如果数据库没有该账号直接跳过下面的if语句
            if (user == null) {
                Member member = new Member();
                member.setOpenid(wxId);
                member.setNickname(nickname);
                member.setAvatar(headimgurl);
                member.setSex(sex);
                memberService.save(member);
            }

            //11.返回首页面,同时将用户信息回显在首页上
            /*
              因为cookie方式不能实现跨域,所以不能直接把微信信息存在cookie中
              我们通过使用jwt生成token字符串,然后把token通过路径传递到首页面进行数据回显
            */
            String token = JwtUtil.getJwtToken(wxId, nickname);
            return "redirect:http://localhost:3000?token="+token;
        } catch (Exception e) {
            e.printStackTrace();
            throw  new CustomException(20001,"登录失败");
        }
    }
}
